package ktvdownloadserver

import (
	"encoding/binary"
	"fmt"
	"ktvserver/core/tcpserver"
	"ktvserver/ktvutil"
	"ktvserver/ktvutil/videopath"
	"log"
	"net"
	"os"
)

//////////////////////////////////////////////////////////////////////////////////////
// 处理歌曲文件请求
//////////////////////////////////////////////////////////////////////////////////////

// 获取歌曲文件信息
func KtvSongFileInfo(w tcpserver.ResponseWriter, req *tcpserver.Request) {

	//fmt.Println("KtvSongFileInfo enter ...")
	//defer fmt.Println("KtvSongFileInfo leave ...")

	info := tcpserver.GetKtvRequestInfo(req.DataBody)

	var dataLength uint32

	// 获取歌曲视频文件路径
	srcFilePath := videopath.GetSongVideoPath(info.Number, info.Ext[:])

	// 获取文件的信息
	if fi, err := os.Stat(srcFilePath); err != nil {
		// 找不到文件直接发送空数据
		dataLength = 0
	} else {
		dataLength = uint32(fi.Size())
	}

	tcpserver.WriteHeader(w, 4, 0)
	binary.Write(w, binary.LittleEndian, &dataLength)
	tcpserver.WriteFooter(w)

}

// 获取系统文件数据
func KtvSongFileData(w tcpserver.ResponseWriter, req *tcpserver.Request) {

	//fmt.Println("KtvSongFileData enter ...")
	//defer fmt.Println("KtvSongFileData leave ...")

	info := tcpserver.GetKtvRequestInfo(req.DataBody)

	// 获取歌曲视频文件路径
	srcFilePath := videopath.GetSongVideoPath(info.Number, info.Ext[:])

	if srcFilePath == "" {
		// 找不到文件直接发送空数据
		fmt.Printf("KtvSongFileData ...%d NOT FOUND, videopath is empty\n", info.Number)
		tcpserver.WriteHeader(w, 0, 0)
		tcpserver.WriteFooter(w)
		return
	}

	// 获取文件的信息
	fi, err := os.Stat(srcFilePath)
	if err != nil || fi.Size() <= 0 {
		// 找不到文件直接发送空数据
		fmt.Printf("KtvSongFileData Number ...%d NOT FOUND, path=%s, err=%v\n", info.Number, srcFilePath, err)
		tcpserver.WriteHeader(w, 0, 0)
		tcpserver.WriteFooter(w)
		return
	}

	// 计算发送的长度
	offset, length := tcpserver.CalcuteTransferParam(fi.Size(), int64(info.Start), int64(info.Length))

	// 打印显示信息
	log.Printf("(%v) GetSongData, number=%d, offset=%d, len=%d",
		req.RemoteIP(),
		info.Number,
		offset,
		length)

	// 发送文件数据
	tcpserver.WriteHeader(w, uint32(length), 0)
	tcpserver.WriteFile(w, srcFilePath, offset, length)
	tcpserver.WriteFooter(w)

}

// 系统文件继续传输
func KtvSongFileContinue(w tcpserver.ResponseWriter, req *tcpserver.Request) {

	//fmt.Println("KtvSongFileContinue enter ...")
	//defer fmt.Println("KtvSongFileContinue leave ...")

	info := tcpserver.GetKtvRequestInfo(req.DataBody)

	// 获取歌曲视频文件路径
	srcFilePath := videopath.GetSongVideoPath(info.Number, info.Ext[:])

	if srcFilePath == "" {
		// 找不到文件直接发送空数据
		fmt.Printf("KtvSongFileData ...%d NOT FOUND, videopath is empty\n", info.Number)
		tcpserver.WriteHeader(w, 0, 0)
		tcpserver.WriteFooter(w)
		return
	}

	// 获取文件的信息
	fi, err := os.Stat(srcFilePath)
	if err != nil || fi.Size() <= 0 {
		// 找不到文件直接发送空数据
		tcpserver.WriteHeader(w, 0, 0)
		tcpserver.WriteFooter(w)
		return
	}

	// 计算发送的长度
	offset, length := tcpserver.CalcuteTransferParam(fi.Size(), int64(info.Start), int64(info.Length))

	// 打印显示信息
	log.Printf("(%v) GetSongData, number=%d, offset=%d, len=%d",
		req.RemoteIP(),
		info.Number,
		offset,
		length)

	// 发送文件数据
	tcpserver.WriteFile(w, srcFilePath, offset, length)

}

// 分配歌曲IP地址
type SongIpList struct {
	SongNum uint32    // 歌曲编号
	Count   uint32    // 当前服务器的个数
	IP      [4]uint32 // 同一首歌最多放在4个服务器上面, 网络字节顺序
	Padding uint32    // 附加信息
	Disk    [4]byte   // 每个服务器上面对应的盘符

	Port     uint16  // 服务器端口
	Reserved [2]byte // 保留字段

	PlayTimeLimit  uint32 //  歌曲播放时间限制,
	ClickToNextNum uint32 // 切歌点击数
}

const KTV_SONG_IP_STRUCT_SIZE = 44

func (s *SongIpList) StructSize() int {
	return KTV_SONG_IP_STRUCT_SIZE
}

// 歌曲IP地址分配
func KtvSongIpList(w tcpserver.ResponseWriter, req *tcpserver.Request) {

	var ipinfo SongIpList

	ktvinfo := tcpserver.GetKtvRequestInfo(req.DataBody)

	ipinfo.SongNum = ktvinfo.Number
	ipinfo.Count = 1
	ipinfo.Port = uint16(ktvutil.GetDownloadServerPort())
	// 默认127.0.0.1
	ipinfo.IP[0] = uint32(127)<<24 | uint32(0)<<16 | uint32(0)<<8 | uint32(1)

	// 本地连接的地址
	localip := net.ParseIP(req.LocalIP()).To4()
	//log.Printf("localip=%s, v=%v", req.LocalIP(), localip)
	if localip != nil {
		ipinfo.IP[0] = uint32(localip[0])<<24 | uint32(localip[1])<<16 | uint32(localip[2])<<8 | uint32(localip[3])
	}

	tcpserver.WriteHeader(w, uint32(ipinfo.StructSize()), 0)
	binary.Write(w, binary.LittleEndian, &ipinfo)
	tcpserver.WriteFooter(w)

}
